module ProxyingHelper
    module ClassMethods

        def define_url_handler(pattern, handler=nil, &block)
            @url_handler_map ||= []
            if block #handler should be nil
                @url_handler_map << [pattern, block]
            else
                @url_handler_map << [pattern, handler]
            end

        end

        def handle(url, doc, object)
            @url_handler_map.select {|x| x[0]=~ url}.each do |pattern, handler|

                if handler.is_a? Symbol
                    object.send(handler, url, doc)
                elsif  handler.is_a? Class
                    handler.url_handle(url, doc)
                elsif handler.is_a? Proc
                    handler.call(url, doc)
                end
            end
        end
    end
    def self.append_features(base)
        base.extend(ClassMethods)
        super
    end

    def url_decode(str)
        str.gsub!(/%[a-fA-F0-9]{2}/) { |x| x = x[1..2].hex.chr }
        str
    end

    def fix_params
        params.delete("controller")
        params.delete("action")
        params.delete("id")
    end

    def fix_contentType

        content_type = @page.content_type
        if content_type ==  "text/html"
            #if file.charset == "iso-8859-1"
            content_type += ";charset=GB2312"  #&& !content_type.grep(/charset/)
            #else
            #content_type += ";charset=#{file.charset}"  #???&& !content_type.grep(/charset/)
            #end
        end
    end

    def fix_result
        @result = @doc.to_html + "original link:<a href=#{url_decode(@url)}>#{url_decode(@url)}</a>"
        @result += "<form action='/proxying' method='get'>navigate to: <input type='text' name='q'></form>"
        @result += "<form action='/proxying/store' method='post'>Store it!: <input type=submit value=submit /></form>"
    end

    def rewrite_link_for_doc(doc)

        rewrite_link(doc, "//img[@src]", "src", false)
        #css link
        rewrite_link(doc, "//link[@href]", "href", false)
        rewrite_link(doc, "//script[@src]", "src", false)

        rewrite_link(doc, '//*[@background]', "background", false)

        #or background:url?
        rewrite_link(doc, '*[@style*=background]', "style.background-url", false)

        #replace every link with relative link to base_url
        rewrite_link(doc, '//a[@href]', "href", true)

        rewrite_link(doc, '//form[@action]', "action", true)

    end


    def rewrite_link(doc, selector, attribute, prefixing_proxy)
        doc.search(selector).to_a.each do |link|
            if attribute.index "."
                attr, attr2 = attribute.split(".")
                attr2.gsub!("-", ":")
                url = link.attributes[attr].scan(/#{attr2}\((.*)\)/)[0]
                #puts "wa:#{url.inspect},#{link}"
                next if url.nil?
                url = url[0]
            else
                url = link.attributes[attribute]
            end

            href = URI(url) rescue URI("#") #we met URI("###"),weird

            if !href.host
                #relative url
                doc_url = URI(@page.uri.to_s) #already URI::###
                if url[0] == ?/
                    to_url = doc_url.scheme + "://" + doc_url.host + url #todo
                else

                    to_url = doc_url.scheme + "://" + doc_url.host
                    to_url += "/" if doc_url.path == ""

                    str = "doc_url.path:#{doc_url.path},url:#{url}"

                    if doc_url.path == ""
                        to_url += url
                    else
                        to_url +=  doc_url.path.gsub!(/\/[^\/]*$/, "/#{url}")
                    end

                    logger.info "#{str}, to_url:#{to_url}"


                end

            else
                to_url = link.attributes[attribute]
            end




            if prefixing_proxy
                to_url = ERB::Util.url_encode(to_url).gsub!(".", "%2E")
            end

            if attribute.index "."
                attr, attr2 = attribute.split(".")
                attr2.gsub!("-", ":")


                if prefixing_proxy
                    #puts "before link:#{link}"
                    to_url = "http://localhost:3000/proxying/"+to_url
                    link.set_attribute(attr, link.attributes[attr].gsub!(/(#{attr2})\((.*)\)/, "\\1(#{to_url})"))
                    #puts "after link:#{link}"
                else
                    link.set_attribute(attr, link.attributes[attr].gsub!(/(#{attr2})\((.*)\)/, "\\1(#{to_url})"))
                end
            else
                if prefixing_proxy
                    link.set_attribute(attribute, "http://localhost:3000/proxying/"+to_url)
                else
                    link.set_attribute(attribute, to_url)
                end
            end

        end
    end

    def initialize_agent
        if session[:agent_id].nil?
            @agent = new_www_agent

            @agent.model = Agent.new
            @agent.model.save!
            session[:agent_id] = @agent.model.id
        else
            model = Agent.find(session[:agent_id])
            @agent = new_www_agent
            @agent.model = model #is this necessary?
            @agent.cookie_jar = YAML.load(@agent.model.cookie_jar)
        end

    end

    def new_www_agent
        agent = WWW::Mechanize.new
        agent.log = logger
        agent.user_agent_alias = 'Windows IE 6'
        agent.max_history = 1 #should be per user agent?
        agent.redirect_ok = true
        class << agent
            attr_accessor :model
        end
        agent
    end

    def dump_agent
        @agent.model.cookie_jar = @agent.cookie_jar
        @agent.model.save! #default use YAML format
        #puts YAML.dump(@agent)
    end

    def baseURL(url)
        url = URI(url)
        path = url.path.clone.gsub!(/\/[^\/]*$/, "/")
        path = "" if path.nil?
        "#{url.scheme}://#{url.host}#{path}"
    end

    def baseURL_withProxyingPrefixed(url)
        url = baseURL(url)
        "http://localhost:3000/proxying/" + ERB::Util.url_encode(url).gsub!(".", "%2E")
    end



    #if file.content_encoding.include?("gzip")
    #unzip it
    #    body_io=StringIO.new(str)
    #    str=Zlib::GzipReader.new(body_io).read
    #end

end
